package club.pinea.client;

import club.pinea.proto.BasicProto;
import club.pinea.proto.CommandProto;
import club.pinea.proto.GameProto;
import club.pinea.proto.LobbyProto;
import club.pinea.session.CallbackContainer;
import club.pinea.session.ClientPlayer;
import club.pinea.session.MessageSend;
import club.pinea.util.PrintUtil;
import club.pinea.util.ResUtil;
import club.pinea.util.ServerResource;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.List;

import static club.pinea.proto.CommandProto.Command.C_S_ROOM_VALUE;

/**
 * @author pineapple
 * @date 2017年12月26日 下午1:31:13
 * @description xxx
 */
@Component
@ChannelHandler.Sharable
public class GameClientHandler extends SimpleChannelInboundHandler<BasicProto.BaseMessage> {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {

        LobbyProto.GameAuthRequest authRequest = LobbyProto.GameAuthRequest.newBuilder()
                .setUserId(ClientPlayer.getUserId())
                .setToken(ClientPlayer.getToken())
                .build();
        MessageSend.sendToUser(authRequest, ctx, (res) -> {
            LobbyProto.GameAuthResponse response = LobbyProto.GameAuthResponse.parseFrom(res.getBody());
            if (ResUtil.isSuccess(response.getRes())) {
                ClientPlayer.setContext(ctx);
                ServerResource.rooms = response.getRoomsList();
                new Thread(()->{
                    serverInRoom();
                }).start();

            }
        });

    }

    /**
     * 选择进入房间
     */
    private void serverInRoom() {
        Assert.notNull(ServerResource.rooms, "房间信息未初始化！");
        LobbyProto.RoomRequest request = PrintUtil.printRoomForm();
        MessageSend.sendToUser(request, ClientPlayer.getContext(), (res) -> {
            LobbyProto.RoomResponse roomResponse = LobbyProto.RoomResponse.parseFrom(res.getBody());
            if (ResUtil.isSuccess(roomResponse.getRes())) {
                ClientPlayer.setMultiplyPower(roomResponse.getMultiplyPower());
                ServerResource.seats = roomResponse.getSeatsList();
                ClientPlayer.setRoomId(request.getRoom());
                new Thread(()->{
                    seatDown();
                }).start();


            }
        });

    }

    /**
     * 进入座位
     */
    private void seatDown() {
        Assert.notNull(ServerResource.seats, "座位信息未初始化");
        LobbyProto.SeatDownRequest request = PrintUtil.printSeatForm();
        MessageSend.sendToUser(request, ClientPlayer.getContext(), (res) -> {
            LobbyProto.SeatDownResponse response = LobbyProto.SeatDownResponse.parseFrom(res.getBody());
            if (ResUtil.isSuccess(response.getRes())) {
                System.out.println(String.format("进入座位【%d】成功", request.getSeatNum()));
                ClientPlayer.setMaxScore(response.getMaxScore());
                ClientPlayer.setMinScore(response.getMinScore());
                ClientPlayer.setBonus(response.getBonusList());
                new Thread(()->{
                    startGame();
                }).start();

            } else {
                System.out.println("进入座位失败，座位信息更新或输入有误");
                ServerResource.seats = response.getSeatsList();
            }
        });
    }

    /**
     * 开始游戏
     */
    private void startGame() {
        Integer choose = PrintUtil.nextScanInt("输入1开始游戏，输入2返回：", "输入错误，请重新输入：");
        switch (choose) {
            case 1:
                Integer score = PrintUtil.nextScanInt(
                        String.format("请输入要押注的分数（%d-%d）：", ClientPlayer.getMinScore(), ClientPlayer.getMaxScore()),
                        "输入错误，请重新输入");
                GameProto.GetCardRequest request = GameProto.GetCardRequest.newBuilder()
                        .setScore(score)
                        .buildPartial();
                MessageSend.sendToUser(request, ClientPlayer.getContext(), (res) -> {
                    GameProto.GetCardResponse response = GameProto.GetCardResponse.parseFrom(res.getBody());
                    if (ResUtil.isSuccess(response.getRes())) {
                        List<Integer> cardsList = response.getCardsList();
                        System.out.println("当前手牌：");
                        cardsList.forEach(i -> System.out.print(PrintUtil.card(i)));
                        System.out.println();
                        new Thread(() -> {
                            replaceCard(cardsList);
                        }).start();

                        // TODO replace card
                    }
                });
                break;
            case 2:
                return;
        }
    }

    /**
     * 换牌
     *
     * @param cardsList
     */
    private void replaceCard(List<Integer> cardsList) {
        String stay = PrintUtil.nextScanInt("请输入要保留的牌的序号：", "输入有误，请重新输入").toString();
        GameProto.ReplaceCardRequest.Builder request = GameProto.ReplaceCardRequest.newBuilder();
        if (!StringUtils.isEmpty(stay)) {
            for (String s : stay.split("")) {
                int i = Integer.parseInt(s);
                request.addCards(cardsList.get(i));
            }
        }
        MessageSend.sendToUser(request.buildPartial(), ClientPlayer.getContext(), (res) -> {
            GameProto.ReplaceCardResponse response = GameProto.ReplaceCardResponse.parseFrom(res.getBody());
            if (ResUtil.isSuccess(response.getRes())) {
                System.out.println("当前手牌：");
                response.getCardsList().forEach(i -> System.out.print(PrintUtil.card(i)));
                System.out.println();
                System.out.println("您当前游戏的结果为：" + PrintUtil.cardType(response.getType()));
                if (response.getType() > 0) {
                    doubleCard(response.getType());
                } else {
                    getScore();
                }
            }
        });
    }

    /**
     * 比倍的方法
     *
     * @param type
     */
    private void doubleCard(int type) {
        int score = ServerResource.scores[ClientPlayer.getRoomId() - 1][type] * ClientPlayer.doublePower[ClientPlayer.getDoubleTime() + 1];
        int choose = PrintUtil.nextScanInt("比倍约能获得：" + score + "分，是否需要比倍？（1是 2否）", "输入错误，请重新输入");
        if (choose == 1) {
            ClientPlayer.setDoubleTime(ClientPlayer.getDoubleTime() + 1);
            GameProto.DoubleCardRequest request = GameProto.DoubleCardRequest.newBuilder().buildPartial();
            MessageSend.sendToUser(request, ClientPlayer.getContext(), (res) -> {
                GameProto.DoubleCardResponse response = GameProto.DoubleCardResponse.parseFrom(res.getBody());
                if (ResUtil.isSuccess(response.getRes())) {
                    if (response.getDoubleWin() > 0) {
                        System.out.println("是否再次比倍？");
                        doubleCard(type);
                    } else {
                        System.out.println("比倍输了。。。");
                        getScore();
                    }
                }
            });
        } else {
            getScore();
        }
    }

    /**
     * 获取当前分数
     */
    private void getScore() {
        ClientPlayer.setDoubleTime(0);
        GameProto.GetScoreRequest request = GameProto.GetScoreRequest.newBuilder().buildPartial();
        MessageSend.sendToUser(request, ClientPlayer.getContext(), (res) -> {
            GameProto.GetScoreResponse response = GameProto.GetScoreResponse.parseFrom(res.getBody());
            if (ResUtil.isSuccess(response.getRes())) {
                System.out.println("当前积分剩余：" + response.getScore());
            }
        });
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, BasicProto.BaseMessage baseMessage) throws Exception {
//        System.out.println("我收到了服务器端发送的数据：" + baseMessage);
        if (baseMessage.getOrder() != CommandProto.Command.S_C_HEART_VALUE) {
            CallbackContainer.doCallback(baseMessage.getOrder(), baseMessage);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        System.out.println("出错了");
        ctx.close();
    }


    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            if (((IdleStateEvent) evt).state() == IdleState.WRITER_IDLE) {
                BasicProto.HeartRequest request = BasicProto.HeartRequest.newBuilder().build();
                MessageSend.sendToUser(request, ctx);
            }
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }

}
